/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package clientside;

import java.io.*;
import java.net.*;
import client.network.*;
import com.cse.p2p.common.CommonSettings;
import com.cse.p2p.common.DicFile;
import com.cse.p2p.common.Message;
import com.cse.p2p.database.ClientDatabase;
import com.cse.p2p.hash.HashImplement;
import com.cse.p2p.parser.FileMetadata;
import java.util.Map;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JProgressBar;

/**
 *
 * @author TuyetNgan
 */
public class ControlClientSide extends Thread {

	private Integer portControl = CommonSettings.CLIENT_SERVERSOCKET;
	private BufferedReader inStream = null;
	private PrintStream outStream = null;
	private DataClientSide dataThread;

	public void run() {
		// TODO code application logic here
		try {
			ServerSocket serverSocket = null;
			boolean listening = true;
			int count = 0;
			try {
				serverSocket = new ServerSocket( portControl );
			}
			catch ( IOException e ) {
				System.err.println( "Could not listen on port: " + portControl );
				System.exit( -1 );
			}
			System.out.println( "Client start control port!" + portControl);
			while ( listening ) {
				( new ClientControlTask_Server( serverSocket.accept() ) ).start();
				count++;
			}
			serverSocket.close();
		}
		catch ( IOException e ) {
		}

	}

	public void uploadNewFileRoutine( String rootFilePath, String targetFilePath, String fileDesc,
									  JLabel lblIndicator, JProgressBar prgIndicator, JButton fireBtn ) {
//		lblIndicator.setText( "Uploading your file to the server ... " );
//		prgIndicator.setIndeterminate( false );
//		prgIndicator.setStringPainted( true );
		File rootFile = new File( rootFilePath );
		System.out.println( rootFilePath );
		if ( !rootFile.exists() ) {
			System.err.println( "The file does not exist!" );
			return;
		}
		try {
			lblIndicator.setText( "Creating file hash ... " );
			prgIndicator.setIndeterminate( false);
			prgIndicator.setStringPainted( true );
			String fileHash = HashImplement.getHashFile( rootFile, prgIndicator );
			System.out.println( fileHash );

			FileMetadata meta = new FileMetadata( rootFilePath, fileDesc, fileHash, rootFile.length() );

			lblIndicator.setText( "Connecting to the server ..." );
			Socket connectServerCtrl = new Socket( CommonSettings.HOST_ADDRESS, CommonSettings.SERVER_SERVERSOCKET );

			BufferedReader inStream = new BufferedReader( new InputStreamReader( connectServerCtrl.getInputStream() ) );
			PrintStream outStream = new PrintStream( connectServerCtrl.getOutputStream() );

			outStream.println( ( new Message( Message.Command.GET, Message.Keyword.UP, meta.toString() ) ) );
			Message response = Message.fromString( inStream.readLine() );
			if ( response.getType() == Message.MsgType.RES_UP_DIC_FILE ) {
				if ( response.getData().equals( "OK" ) ) {

					try {
						sleep( 500 ); // wait the server update connection list
					}
					catch ( InterruptedException inEx ) {
						System.err.println( inEx.getMessage() );
					}

					Socket dataSendingSck = new Socket( CommonSettings.HOST_ADDRESS, CommonSettings.SERVER_DATA_SERVERSOCKET );

					lblIndicator.setText( "Transfering your file ..." );
					prgIndicator.setIndeterminate( false );
					prgIndicator.setStringPainted( true );

					FileInputStream fis = new FileInputStream( rootFile );
					byte[] buffer = new byte[ CommonSettings.DEFAULT_PACKAGE_SIZE ];
					long done = 0;
					long total = rootFile.length();
					int readResult = 0;

					OutputStream dataSendingOS = dataSendingSck.getOutputStream();
					while ( ( readResult = fis.read( buffer ) ) > 0 ) {
						dataSendingOS.write( buffer, 0, readResult );
						done += readResult;
						int percent = Math.round( ( ( float ) done ) / total * 100 );
//						System.out.println( done + " " + total + " " + percent);
						prgIndicator.setValue( percent );
						prgIndicator.setString( null );
						prgIndicator.repaint();
						dataSendingOS.flush();
					}
					dataSendingSck.close();

					prgIndicator.setValue( 0 );
					prgIndicator.setIndeterminate( true );
					prgIndicator.setString( "" );
					prgIndicator.repaint();
					lblIndicator.setText( "Waiting for Dic file" );

					response = Message.fromString( inStream.readLine() );
					if ( response.getType() == Message.MsgType.REQ_UP_DIC_FILE ) {
						lblIndicator.setText( "Recieving the Dic file" );
						StringWriter sw = new StringWriter();
						sw.write( inStream.readLine() );
						sw.flush();
						DicFile newDicfile = DicFile.parseDicFileFromXML( sw.toString() );
						BufferedOutputStream bos = new BufferedOutputStream( new FileOutputStream( new File( targetFilePath ) ) );
						bos.write( sw.toString().getBytes() );
						bos.close();
						sw.close();
						outStream.println( new Message( Message.Command.PUT, Message.Keyword.UP, "OK" ) );
						lblIndicator.setText( "The Dic file is saved!" );
						prgIndicator.setIndeterminate( false );
						prgIndicator.setValue( 100 );
						prgIndicator.repaint();
						connectServerCtrl.close();

						File fileFolder = new File( CommonSettings.DEFAULT_TEMP_FOLDER + File.separatorChar + newDicfile.getFileID() );
						if ( fileFolder.exists() ) {
							fileFolder.delete();
						}
						else {
							fileFolder.mkdirs();
						}

						lblIndicator.setText( "Preparing your file to make it ready ..." );
						prgIndicator.setValue( 0 );
						prgIndicator.repaint();
						FileInputStream tempPieceFIS = new FileInputStream( rootFile );
						int pieceNo = 0;
						while ( ( readResult = tempPieceFIS.read( buffer ) ) > 0 ) {
							prgIndicator.setValue( ( int ) ( ( double ) pieceNo / newDicfile.getPieceHash().size() * 100 ) );
							prgIndicator.repaint();
							String tempPiecePath = fileFolder.getAbsolutePath() + File.separatorChar + pieceNo;
							BufferedOutputStream tempPieceBOS = new BufferedOutputStream( new FileOutputStream( new File( tempPiecePath ) ) );
							tempPieceBOS.write( buffer, 0, readResult );
							tempPieceBOS.close();
							pieceNo++;
						}

//						ClientDatabase.openDatabase();
						ClientDatabase.NewFile( newDicfile.getFileName(), newDicfile.getFileName() + System.currentTimeMillis(), newDicfile.getFileID(), newDicfile.getFileSize(), rootFilePath, "", "" );
						Map hashMap = newDicfile.getPieceHash();
						int newFileID = newDicfile.getFileID();
						for (pieceNo = 0; pieceNo < hashMap.size(); pieceNo++){
							ClientDatabase.NewPiece( pieceNo, newFileID, (String)hashMap.get( pieceNo) );
						}
//						ClientDatabase.closeDatabase();
						lblIndicator.setText( "All things done." );
						fireBtn.setEnabled( true );
						
					}

				}
				else {
					System.err.println( "Cannot transfer file to host." );
				}
			}

		}
		catch ( Exception e ) {
			System.err.println( e.getMessage() );
			e.printStackTrace();
		}
	}
	
	public void setDataThread(DataClientSide thread){
		this.dataThread = thread;
	}
}
